package de.stefanocke.roo.wicket

import org.apache.felix.scr.annotations.Component
import org.apache.felix.scr.annotations.Reference
import org.apache.felix.scr.annotations.Service
import org.springframework.roo.classpath.PhysicalTypeIdentifier
import org.springframework.roo.classpath.TypeLocationService
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails
import org.springframework.roo.model.JavaSymbolName
import org.springframework.roo.model.JavaType


@Component
@Service
class ApplicationServiceImpl implements ApplicationService {
	
	@Reference
	TypeLocationService typeLocationService
	
	override findClassOrInterfaceDetailsWithStereotype(String moduleName, String stereotype){
		val stereotypeAnnotation = new JavaType(typeof(RooStereotype).name)
		val typesWithStereotypeAnnotation = 
			typeLocationService
			.findClassesOrInterfaceDetailsWithAnnotation(stereotypeAnnotation)
			.filter(t | moduleName == null || t.isInModule(moduleName))
		val innerTypes = typesWithStereotypeAnnotation.map(t | t.declaredInnerTypes).flatten
		
		val stereotypeFilter = [ClassOrInterfaceTypeDetails t |{ 		
				val a =	t.getAnnotation(stereotypeAnnotation) 		
				val av = a?.getAttribute(new JavaSymbolName("value"))
				stereotype.equals(av?.value)
			}]
			
		var candidates = typesWithStereotypeAnnotation.filter(stereotypeFilter).toSet
			
		candidates.addAll(innerTypes.filter(stereotypeFilter));
		
		if(candidates.size>1){
			throw new ValidationException("Multiple classes with @RooStereotype("+stereotype+") found: "
				+candidates.map(c|c.name.fullyQualifiedTypeName+" "));
		}
		if(candidates.empty) null else candidates.iterator.next
	}

	override getWebPackage(String moduleName) {
		val app = findClassOrInterfaceDetailsWithStereotype(moduleName, Stereotypes::APPLICATION)
		app?.name?.^package 
	}
	
	def isInModule(ClassOrInterfaceTypeDetails cid, String module){
		module.equals(PhysicalTypeIdentifier::getPath(cid.declaredByMetadataId).module)
		//TODO: also allow the stereotype do be in a dependency module
	}

}
